home *** CD-ROM | disk | FTP | other *** search
- /*
- * The functions in this file maintain a hash table of strings and manage
- * string buffers.
- */
- #include "::h:gsupport.h"
-
- /*
- * Prototype for static function.
- */
- hidden int streq Params((int len,char *s1,char *s2));
-
- /*
- * Entry in string table.
- */
- struct str_entry {
- char *s; /* string */
- int length; /* length of string */
- struct str_entry *next;
- };
-
- #define SBufSize 1024 /* initial size of a string buffer */
- #define StrTblSz 149 /* size of string hash table */
- static struct str_entry **str_tbl = NULL; /* string hash table */
-
- /*
- * init_str - initialize string hash table.
- */
- novalue init_str()
- {
- int h;
-
- if (str_tbl == NULL) {
- str_tbl = (struct str_entry **)alloc((unsigned int)(StrTblSz *
- sizeof(struct str_entry *)));
- for (h = 0; h < StrTblSz; ++h)
- str_tbl[h] = NULL;
- }
- }
-
- /*
- * free_stbl - free string table.
- */
- novalue free_stbl()
- {
- struct str_entry *se, *se1;
- int h;
-
- for (h = 0; h < StrTblSz; ++h)
- for (se = str_tbl[h]; se != NULL; se = se1) {
- se1 = se->next;
- free((char *)se);
- }
-
- free((char *)str_tbl);
- str_tbl = NULL;
- }
-
- /*
- * init_sbuf - initialize a new sbuf struct, allocating an initial buffer.
- */
- novalue init_sbuf(sbuf)
- struct str_buf *sbuf;
- {
- sbuf->size = SBufSize;
- sbuf->frag_lst = (struct str_buf_frag *)alloc((unsigned int)
- (sizeof(struct str_buf_frag) + (SBufSize - 1)));
- sbuf->frag_lst->next = NULL;
- sbuf->strtimage = sbuf->frag_lst->s;
- sbuf->endimage = sbuf->strtimage;
- sbuf->end = sbuf->strtimage + SBufSize;
- }
-
- /*
- * clear_sbuf - free string buffer storage.
- */
- novalue clear_sbuf(sbuf)
- struct str_buf *sbuf;
- {
- struct str_buf_frag *sbf, *sbf1;
-
- for (sbf = sbuf->frag_lst; sbf != NULL; sbf = sbf1) {
- sbf1 = sbf->next;
- free((char *)sbf);
- }
- sbuf->frag_lst = NULL;
- sbuf->strtimage = NULL;
- sbuf->endimage = NULL;
- sbuf->end = NULL;
- }
-
- /*
- * new_sbuf - allocate a new buffer for a sbuf struct, copying the partially
- * created string from the end of full buffer to the new one.
- */
- novalue new_sbuf(sbuf)
- struct str_buf *sbuf;
- {
- struct str_buf_frag *sbf;
- char *s1, *s2;
-
- /*
- * The new buffer is larger than the old one to insure that any
- * size string can be buffered.
- */
- #if IntBits == 16
- unsigned int oldsize = sbuf->size;
- sbuf->size += (sbuf->size/2);
- if (sbuf->size < oldsize) { /* check for overflow */
- sbuf->size = MaxBlock;
- }
- #else /* IntBits == 16 */
- sbuf->size *= 2;
- #endif /* IntBits == 16 */
-
- s1 = sbuf->strtimage;
- sbf = (struct str_buf_frag *)alloc((unsigned int)
- (sizeof(struct str_buf_frag) + (sbuf->size - 1)));
- sbf->next = sbuf->frag_lst;
- sbuf->frag_lst = sbf;
- sbuf->strtimage = sbf->s;
- s2 = sbuf->strtimage;
- while (s1 < sbuf->endimage)
- *s2++ = *s1++;
- sbuf->endimage = s2;
- sbuf->end = sbuf->strtimage + sbuf->size;
- }
-
- /*
- * spec_str - install a special string (null terminated) in the string table.
- */
- char *spec_str(s)
- char *s;
- {
- struct str_entry *se;
- register char *s1;
- register int l;
- register int h;
-
- h = 0;
- l = 1;
- for (s1 = s; *s1 != '\0'; ++s1) {
- h += *s1 & 0377;
- ++l;
- }
- h %= StrTblSz;
- for (se = str_tbl[h]; se != NULL; se = se->next)
- if (l == se->length && streq(l, s, se->s))
- return se->s;
- se = NewStruct(str_entry);
- se->s = s;
- se->length = l;
- se->next = str_tbl[h];
- str_tbl[h] = se;
- return s;
- }
-
- /*
- * str_install - find out if the string at the end of the buffer is in
- * the string table. If not, put it there. Return a pointer to the
- * string in the table.
- */
- char *str_install(sbuf)
- struct str_buf *sbuf;
- {
- int h;
- struct str_entry *se;
- register char *s;
- register char *e;
- int l;
-
- AppChar(*sbuf, '\0') /* null terminate the buffered copy of the string */
- s = sbuf->strtimage;
- e = sbuf->endimage;
-
- /*
- * Compute hash value.
- */
- h = 0;
- while (s < e)
- h += *s++ & 0377;
- h %= StrTblSz;
- s = sbuf->strtimage;
- l = e - s;
- for (se = str_tbl[h]; se != NULL; se = se->next)
- if (l == se->length && streq(l, s, se->s)) {
- /*
- * A copy of the string is already in the table. Delete the copy
- * in the buffer.
- */
- sbuf->endimage = s;
- return se->s;
- }
-
- /*
- * The string is not in the table. Add the copy from the buffer to the
- * table.
- */
- se = NewStruct(str_entry);
- se->s = s;
- se->length = l;
- sbuf->strtimage = e;
- se->next = str_tbl[h];
- str_tbl[h] = se;
- return se->s;
- }
-
- /*
- * streq - compare s1 with s2 for len bytes, and return 1 for equal,
- * 0 for not equal.
- */
- static int streq(len, s1, s2)
- register int len;
- register char *s1, *s2;
- {
- while (len--)
- if (*s1++ != *s2++)
- return 0;
- return 1;
- }
-